/*
 * PRedisBase.h
 *
 *  Created on: Oct 11, 2013
 *      Author: yuliang
 */

#ifndef PREDISBASE_H_
#define PREDISBASE_H_

#include <stdint.h>
#include <hiredis/hiredis.h>
#include <string>
#include <vector>

#ifndef LOG_REDIS
#define LOG_REDIS "logRedis"
#endif

/*
 * @brief       redis连接操作基类
 * @auther      lyl
 */
class CPRedisBase {
public:
	#define RedisNone 0
	#define RedisError -1
	typedef std::vector<std::string> VecStr_t;

	typedef struct RedisConfig {
		const char *host;
		const char *db;
		int port;
		int timeout;
	} sRedisConfig;
public:
	CPRedisBase();
	virtual ~CPRedisBase();

	bool TimeConnect(const sRedisConfig* config);
	void Disconnect();
	bool Reconnect();
	inline redisContext *GetRedisContext() { return m_redisContext; }

	int32_t DelKey(const std::string& key);
	int32_t OutTime(const std::string& key, uint32_t sec);

	int32_t StringAdd(const std::string& key, const std::string& value);
	int32_t StringGet(const std::string& key, std::string& value);
	int32_t StringIncrby(const std::string& key, int32_t value = 1);

	int32_t HashAdd(const std::string& key, const std::string& field, const std::string& value);
	int32_t HashMAdd(const std::string& key, const VecStr_t& field, const VecStr_t& value);
	int32_t HashGet(const std::string& key, const std::string& field, std::string& value);
	int32_t HashMGet(const std::string& key, const VecStr_t& field, VecStr_t& value);
	int32_t HashGetAll(const std::string& key, VecStr_t& value);
	int32_t HashDel(const std::string& key, const std::string& field);
	int32_t HashMDel(const std::string& key, const VecStr_t& field);
	int32_t HashIncrby(const std::string& key, const std::string& field, int32_t value = 1);

	int32_t SetAdd(const std::string& key, const std::string& value);
	int32_t SetMAdd(const std::string& key, const VecStr_t& value);
	int32_t SetExist(const std::string& key, const std::string& value);
	int32_t SetDel(const std::string& key, const std::string& value);
	int32_t SetMDel(const std::string& key, const VecStr_t& value);

private:
	bool SelectDB(const char* redisdb);
	inline bool checkInit();
	inline void decodeArray(const redisReply* r, VecStr_t& value);

#ifdef _UNITTEST
public:
#else
private:
#endif
	void Flushall();
	void FlushDB();
protected:
	redisContext* m_redisContext;
	sRedisConfig m_redisConfig;
	std::string m_Query;
};

bool CPRedisBase::checkInit() {
	if (NULL == m_redisContext) {
		if (!this->Reconnect())
			return false;
	}
	return true;
}

void CPRedisBase::decodeArray(const redisReply* r, VecStr_t& value) {
	for (size_t i = 0; i != r->elements; ++i) {
		redisReply* tr = r->element[i];
		if (NULL != tr) {
			if (tr->type == REDIS_REPLY_STRING)
				value.push_back(tr->str);
			else
				value.push_back("");
		}
	}
}

#endif /* PREDISBASE_H_ */
